package org.arl.modem.transportARQ;

import jade.core.AID;

import java.util.Random;

import org.arl.modem.ATCmd;
import org.arl.modem.ATCommand;
import org.arl.modem.ATCommandInterpreter;
import org.arl.modem.ATNtf;
import org.arl.modem.CommandHandler;
import org.arl.modem.FAPIMessage;

public class TransportARQCommands extends CommandHandler {
	private AID tsp;

	public TransportARQCommands(ATCommandInterpreter agent) {
		super("~T", agent);
		agent.subscribeTopic(TransportARQ.NOTIFICATIONS);
		this.tsp = new AID(agent.getAgentProperty("tsp", "tsp"),
				AID.ISLOCALNAME);

	}

	@ATCmd("AT~TP? - list parameter names")
	public boolean Pq(ATCommand c) {
		output(getParamHelp(TransportParam.class));
		return true;
	}

	@ATCmd("AT~TP.param=value - set parameter\n"
			+ "AT~TP.param? - get parameter")
	// / @see TransportParam for list of supported parameters.
	public boolean P_(ATCommand c) {
		return handleParams(tsp, TransportParam.class, c);
	}

	@ATCmd("AT~TTX.PKT=src,dest,len - transmit packet")
	public boolean TX_PKTz(ATCommand c) {

		return doTxPkt(c);

	}

	@ATCmd("AT~TTX.TESTPKT=src,dest[,len] - transmit a test packet")
	public boolean TX_TESTPKTz(ATCommand c) {
		// if (c.cmd.length <= 3)
		// System.out.println("command has :" + c.cmd[0] + ":" + c.cmd[1]
		// + ":" + c.cmd[2]);
		// else if (c.cmd.length <= 2)
		// System.out.println("command has :" + c.cmd[0] + ":" + c.cmd[1]);
		// else
		// System.out.println("command has :" + c.cmd[0]);
		System.out.println("in command testpkt");
		return doTxPktTest(c);

	}

	private boolean doTxPktTest(ATCommand c) {
		FAPIMessage msg = agent.createMessage(FAPIMessage.REQUEST, tsp);
		if (c.param.length == 3) {

			msg.add("len", c.param[2]);
			Random r = new Random();
			int[] intData = new int[c.param[2] * 2];
			byte[] bytes = new byte[c.param[2]];
			StringBuffer buf = new StringBuffer(2 * c.param[2]);
			for (int i = 0; i < c.param[2] * 2; i++) {
				intData[i] = r.nextInt(10);
				buf.append(i);
			}
			try {
				for (int i = 0; i < c.param[2]; i++)
					bytes[i] = (byte) Integer.parseInt(
							buf.substring(2 * i, 2 * i + 2), 16);
			} catch (NumberFormatException ex) {
				error("Could not interpret data as hexadecimal");
				return false;
			}
			msg.setData(bytes);
			String s = new String(bytes);
			System.out.println("Random data by at command:" + s);
		} else {
			System.out.println("inside else");
			msg.add("len", 0);
			msg.setData(new byte[0]);
		}
		msg.add("src", c.param[0]);
		msg.add("dest", c.param[1]);
		msg.add("tx", 1);
		System.out.println("do test pkt in end");
		return sendAndCheckAck(msg);

	}

	@ATNtf("~TRX.DATA=src,dst,len,pktnumber - received transport layer DATA packet\n"
			+ "~TRX.ACK=src,dst,len - received transport layer ACK packet\n")
	public boolean processNotification(FAPIMessage msg) {
		if (!msg.getSender().equals(tsp))
			return false;
		int rx = msg.getAsInteger("RX", 0);
		String type = msg.get("TYPE");
		if (rx == 1) {

			byte[] data = msg.getData();
			StringBuffer s = new StringBuffer();
			s.append("~T" + type + "=");
			s.append(msg.get("src"));
			s.append(',');
			s.append(msg.get("dest"));
			s.append(',');
			s.append((data == null) ? 0 : data.length);
			TransportPacket tp = new TransportPacket();
			if (data != null) {
				tp.decode(data);
				s.append(',');
				s.append("PacketID:" + tp.packetId);
			}

			if (data != null) {

				s.append('\n');
				s.append(formatBytes(data, 0, data.length));
			}

			output(s.toString());
		}

		return true;
	}

	public boolean doTxPkt(ATCommand c) {
		FAPIMessage msg = agent.createMessage(FAPIMessage.REQUEST, tsp);
		msg.add("src", c.param[0]);
		msg.add("dest", c.param[1]);
		// msg.add("len", c.param[2]);
		msg.add("tx", 1);
		byte[] data = readHexData(c.param[2]);
		String s = new String(data);
		System.out.println("data input by user at command:" + s);
		msg.setData(data);

		return sendAndCheckAck(msg);

	}

}
